﻿#if (NET40 || NET45 || NET471)

using Com.Ctrip.Framework.Apollo;
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;

namespace ApolloExtension
{

    /// <summary>
    /// 需要在AppSetting 中配置 Apollo.AppId,Apollo.Timeout,Apollo.MetaServer等参数
    /// </summary>
    public class ApolloConfig
    {
        private const string defaultNamespace = "application";
        private static Com.Ctrip.Framework.Apollo.IConfig _config;
        private static ConcurrentDictionary<string, IConfig> _dic = new ConcurrentDictionary<string, IConfig>();

        static ApolloConfig()
        {
            _config = ApolloConfigurationManager.GetConfig(defaultNamespace).GetAwaiter().GetResult();
            _dic[defaultNamespace] = _config;
#if DEBUG
            Com.Ctrip.Framework.Apollo.Logging.LogManager.UseConsoleLogging(Com.Ctrip.Framework.Apollo.Logging.LogLevel.Trace);
            _config.ConfigChanged += new Com.Ctrip.Framework.Apollo.ConfigChangeEvent(OnChanged);
#endif
        }
        private static void OnChanged(Com.Ctrip.Framework.Apollo.IConfig sender, Com.Ctrip.Framework.Apollo.Model.ConfigChangeEventArgs args)
        {
            foreach (string key in args.ChangedKeys)
            {
                var change = args.GetChange(key);
                Console.WriteLine("DEBUG Change-key: {0}, oldValue: {1}, newValue: {2}, changeType: {3}", change.PropertyName, change.OldValue, change.NewValue, change.ChangeType);
            }
        }

        /// <summary>
        /// 根据 key 获取 Value
        /// </summary>
        /// <param name="key">key</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns></returns>
        public static string Get(string key, string defaultValue = null)
        {
            return _config.GetProperty(key: key, defaultValue: defaultValue);
        }

        /// <summary>
        /// 获取配置中所有的key
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<string> GetKeys()
        {
            return _config.GetPropertyNames();
        }
        public static ApolloConfig AppSettings { get; } = new ApolloConfig();
        public static ApolloConfig ConnectionStrings { get; } = new ApolloConfig();
        public string this[string key]
        {
            get
            {
                return Get(key);
            }
        }

        public static IConfig GetConfigByNameSpace(string namespaceName)
        {
            return _dic.GetOrAdd(namespaceName, key =>
            {
                var config = ApolloConfigurationManager.GetConfig(namespaceName).GetAwaiter().GetResult();
                _dic[namespaceName] = config;
                return config;
            });
        }

        public static IConfig GetConfigByNameSpace(string[] namespaceNames)
        {
            if (namespaceNames == null || namespaceNames.Length < 1)
                throw new ArgumentNullException(nameof(namespaceNames));
            string name = null;
            namespaceNames.Distinct().ToList().ForEach(_ =>
            {
                name += $"{_},";
            });
            name = name.Trim(',');
            return _dic.GetOrAdd(name, key =>
            {
                var config = ApolloConfigurationManager.GetConfig(namespaceNames).GetAwaiter().GetResult();
                _dic[name] = config;
                return config;
            });
        }
    }

    /// <summary>
    /// <see cref="IConfig"/>扩展方法
    /// </summary>
    public static class ApolloConfigExtension
    {
        /// <summary>
        /// 获取配置中所有的key
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<string> GetKeys(this IConfig config)
        {
            return config.GetPropertyNames();
        }

        /// <summary>
        /// 根据 key 获取 Value
        /// </summary>
        /// <param name="key">key</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns></returns>
        public static string Get(this IConfig config, string key, string defaultValue = null)
        {
            return config.GetProperty(key: key, defaultValue: defaultValue);
        }
    }
}
#endif